package com.partner.boot.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.partner.boot.common.Constants;
import com.partner.boot.common.Result;
import com.partner.boot.controller.domain.UserRequest;
import com.partner.boot.entity.User;
import com.partner.boot.exception.ServiceException;
import com.partner.boot.mapper.UserMapper;
import com.partner.boot.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.partner.boot.utils.EmailUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.jws.Oneway;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 刘孟坤
 * @since 2023-07-30
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    //这里是用来模拟验证码5min时效的，也可以换做redis实现
    //key是验证码，long是时间戳
    private static final Map<String, Long> CODE_MAP = new ConcurrentHashMap<>();

    private static final long TIME_IN_MS5 = 5 * 60 * 1000;
    @Resource
    private UserMapper userMapper;

    @Autowired
    private EmailUtils emailUtils;

    /**
     * @description: 登录
     * @author 刘孟坤
     * @date: 2023/8/9 23:43
     * @param: user
     * @return: com.partner.boot.entity.User
     */
    @Override
    public User login(UserRequest user) {
        User dbUser = null;
        try {
            dbUser = getOne(new UpdateWrapper<User>().eq("username", user.getUsername()).or()
                    .eq("email", user.getUsername()));
        } catch (Exception e) {
            throw new RuntimeException("数据库异常！");
        }
        if (null == dbUser) {
            throw new ServiceException("未找到用户！");
        }
        if (!user.getPassword().equals(dbUser.getPassword())) {
            throw new ServiceException("用户名或密码错误！");
        }
        return dbUser;
    }

    /**
     * @description: 注册
     * @author 刘孟坤
     * @date: 2023/8/9 23:44
     * @param: user
     * @return: com.partner.boot.entity.User
     */
    @Override
    public User register(UserRequest user) {
        //校验邮箱
        validateEmail(user.getEmail(), user.getEmailCode());
        try {
            User saveUser = new User();
            BeanUtils.copyProperties(user, saveUser);
            return saveUser(saveUser);
        } catch (Exception e) {
            throw new RuntimeException("数据库异常！", e);
        }
    }

    /**
     * @description: 保存用户通用代码
     * @author 刘孟坤
     * @date: 2023/8/2 0:25
     * @param: user
     * @return: com.partner.boot.entity.User
     */
    private User saveUser(User user) {
        User dbUser = null;
        dbUser = getOne(new UpdateWrapper<User>().eq("username", user.getUsername()));
        if (null != dbUser) {
            throw new ServiceException("该账号已存在！");
        }
        if (StringUtil.isBlank(user.getPassword())) {
            //设置默认密码
            user.setPassword("lmk666");
        }
        if (StringUtil.isBlank(user.getEmail())) {
            throw new ServiceException("邮箱不能为空！");
        }
        if (Pattern.compile(Constants.EMAIL_PATTERN).matcher(user.getEmail()).matches()) {
            throw new ServiceException("邮箱不正确！");
        }
        if (StringUtil.isBlank(user.getName())) {
            user.setName(Constants.USER_NAME_PREFIX + DateUtil.format(new Date(), Constants.DATE_RULE_YYYYMMDD)
                    + RandomUtil.randomNumbers(6));
        }
        //设置用户唯一标识
        user.setUid(IdUtil.fastSimpleUUID());
        try {
            userMapper.insert(user);
        } catch (Exception e) {
            throw new RuntimeException("注册失败！", e);
        }
        return user;
    }

    /**
     * @description: 发送邮件
     * @author 刘孟坤
     * @date: 2023/8/9 23:44
     * @param: email
     * type
     * @return: void
     */
    @Override
    public void sendEmail(String email, String type) {
        String randomNumbers = RandomUtil.randomNumbers(6);
        log.info("验证码是：{}", randomNumbers);
//		String htmlContext = "<b>尊敬的用户:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" +
//				"您好，partner网提醒您本次的验证码为【{"+ randomNumbers +"}】，有效期5分钟。<br><br><br><b>Partner</b>";
        String htmlContext = "<b>尊敬的用户:</b><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" +
                "您好，partner网提醒您本次的验证码为【{}】，有效期5分钟。<br><br><br><b>Partner</b>";
        String formatHtml = StrUtil.format(htmlContext, randomNumbers);
        User user = getOne(new QueryWrapper<User>().eq("email", email));
        //无需权限验证，即可发送邮箱验证码
        if (Constants.EMAILREGISTER.equals(type)) {
            // 校验邮箱是否已注册
            if (user != null) {
                throw new ServiceException("邮箱已注册");
            }
            //多线程执行异步请求，防止网络阻塞
            ThreadUtil.execAsync(() -> {
                emailUtils.sendHtml("【Partner】邮箱验证提醒", formatHtml, email);
            });
        }
        CODE_MAP.put(randomNumbers + email, System.currentTimeMillis());
    }

    /**
     * @description: 重置密码
     * @author 刘孟坤
     * @date: 2023/8/9 23:44
     * @param: userRequest
     * @return: java.lang.String
     */
    @Override
    public String resetPassword(UserRequest userRequest) {
        String email = userRequest.getEmail();
        User dbUser = getOne(new UpdateWrapper<User>().eq("email", email));
        if (null == dbUser) {
            throw new ServiceException("未找到用户！");
        }
        //校验邮箱
        validateEmail(userRequest.getEmail(), userRequest.getEmailCode());
        String newPass = "123";
        dbUser.setPassword(newPass);
        try {
            int i = userMapper.updateById(dbUser);
            if (i <= 0) {
                throw new ServiceException("未找到用户");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return newPass;
    }

    /**
     * @description: 校验邮箱
     * @author 刘孟坤
     * @date: 2023/8/9 23:44
     * @param: emailCode
     * @return: void
     */
    private void validateEmail(String email, String emailCode) {
        Long timeStamp = CODE_MAP.get(emailCode + email);
        if (null == timeStamp) {
            throw new ServiceException("请先验证邮箱!");
        }
        //验证码时效性在5min内
        if (System.currentTimeMillis() - timeStamp > TIME_IN_MS5) {
            throw new ServiceException("验证码时效性已过！");
        }
        CODE_MAP.remove(emailCode);
    }

    public User goodFirstLogin(String username) {
        return getOne(new UpdateWrapper<User>().eq("username", username));
    }

}
